6
6
.
.
3
3
P
P
r
r
o
o
p
p
e
e
r
r
t
t
y
y
W
W
r
r
a
a
p
p
p
p
e
e
r
r
s
s
$
$
$ before the Variable name means a reference to a variable (and not the actual value).
$
$
a
a
n
n
d
d
@
@
S
S
t
t
a
a
t
t
e
e
So in below example TextField gets a reference to name which allows TextField to update name as the User types text.
But for this to work name must be @State variable (since otherwise it will be immutable and it couldn’t change).
And since name is @State variable any change to it (like Button action) will also update Views that use it like TextField.
TextField second Parameter can only accept Reference to String Variable.
So when $ is used in combination with @State it synchs variable and View Property
Changes made to TextField View are automatically copied into name Variable (by using provided reference to name)
Changes made to name Variable are automatically copied into TextField View (since name is @State variable)
$ and @State
import SwiftUI
struct ContentView: View {
@State var name = ""
var body: some View {
VStack {
TextField("Enter name", text: $name) //Update variable as you type. Give referene to variable.
Button("Button") { self.name = "Thank you" } //Update @State variable.
Text(name) //Automatically redraw View when @State variable changes.
}
}
}
@
@
S
S
t
t
a
a
t
t
e
e
@State Variables are used to
Redraw View (automatically when their value changes)
Access View Properties (as a proxy to indirectly read and write View Properties to which they are assigned)
Change struct Property (by default struct and its Properties are immutable)
ContentView.swift
struct ContentView: View {
@State var name = "John"
var body: some View {
VStack {
Button("Button") { self.name = "Bill" } //Update @State variable.
Text(name) //Automatically redraw View when @State variable changes.
}
}
}
@
@
B
B
i
i
n
n
d
d
i
i
n
n
g
g
@Binding is used to declare that Variable is a Reference to another Variable (points to another Variable).
We use $ before the Variable name to give a reference to a Variable like $show.
In below example we use this to control variable show from another View (through isShown).
Steps to reproduce: First create Text and normal button that toggles show. Then create struct ToggleButton that toggles
isPresented. Then instantiate ToggleButton by giving it reference to show as parameter.
ContentView.swift (pressing button changes text color)
import SwiftUI
struct ContentView : View {
@State var show = true
var body:some View {
VStack(spacing: 20) {
Text("TEXT").foregroundColor(show ? .blue : .red)
ToggleButton(isShown: self.$show)
}
}
}
struct ToggleButton : View {
@Binding var isShown : Bool
var body : some View {
Button("TOGGLE") { self.isShown.toggle() }
}
}
@
@
P
P
u
u
b
b
l
l
i
i
s
s
h
h
e
e
d
d
,
,
@
@
O
O
b
b
s
s
e
e
r
r
v
v
e
e
d
d
O
O
b
b
j
j
e
e
c
c
t
t
When Property marked as @Published is changed, body Property of any View that uses that Property will be redrawn.
@Published can be used only inside a Class that implements ObservableObject Protocol.
Instance of such Class must be flagged with @ObservedObject (to say that you actually want to use this feature).
ContentView.swift
import SwiftUI
class Person : ObservableObject { //Can be Observed
@Published var name = "John" //Only changes to this variable should be observed
}
struct ContentView: View {
@ObservedObject var person = Person() //Observer ObservableObject
var body: some View {
VStack {
Button("Button") { self.person.name = "Bill" } //Update @Published variable.
Text(person.name) //Redraw View when @Published variable changes
}
}
}
@
@
E
E
n
n
v
v
i
i
r
r
o
o
n
n
m
m
e
e
n
n
t
t
O
O
b
b
j
j
e
e
c
c
t
t
If Variable is declared as @EnvironmentObject then SwiftUI will try to find an Instance with this name in Environment.
ContentView.swift
import SwiftUI
//==========================================================================
// Person
//==========================================================================
class Person : ObservableObject { //Must conform to ObservableObject Protocol
var name = "John" //Otherwise you can't use @EnvironmentObject
}
//==========================================================================
// ContentView
//==========================================================================
struct ContentView: View {
var person = Person() //Create person Instance
var body: some View {
DetailView().environmentObject(person) //Put person Instance into Environment
}
}
//==========================================================================
// DetailView
//==========================================================================
struct DetailView : View {
@EnvironmentObject var person : Person //Get person Instance from Environment
var body : some View {
Text(person.name)
}
}